#pragma once
#include "afxwin.h"
#include "Winuser.h"
//#include "DialogAsControl.h"

#define ALIGNMENT_AXIS_NO						0
#define ALIGNMENT_AXIS_1						1
#define ALIGNMENT_AXIS_2						2
#define ALIGNMENT_AXIS_3						3
#define ALIGNMENT_AXIS_4						4
#define ALIGNMENT_AXIS_5						5
#define ALIGNMENT_AXIS_6						6




//alg v2.0 specific --------

#define ALIGNMENT_AXIS_VertNo					ALIGNMENT_AXIS_NO
#define ALIGNMENT_AXIS_HorNo					ALIGNMENT_AXIS_NO

#define ALIGNMENT_AXIS_VertLeft					ALIGNMENT_AXIS_1	
#define ALIGNMENT_AXIS_VertMid					ALIGNMENT_AXIS_2
#define ALIGNMENT_AXIS_VertRight				ALIGNMENT_AXIS_3
#define ALIGNMENT_AXIS_HorUp					ALIGNMENT_AXIS_4
#define ALIGNMENT_AXIS_HorMid					ALIGNMENT_AXIS_5
#define ALIGNMENT_AXIS_HorDown					ALIGNMENT_AXIS_6

#define ALIGNMENT_MasterID_DefWin				1

#define ALIGNMENT_AutoDetectOffset				INT_MAX

//end alg v2.0 specific ----



#define SIZE_NORESIZE								-1



class CWndProperties
{
public:
	UINT wndID;
	HWND hwndID;//only for dinamic created windwos
	CRect crDefPosition;
	CRect crPosition;
	bool bXExpandable;
	bool bYExpandable;
	UINT wndMasterXID;
	UINT wndMasterYID;
	int nMasterXAxis;
	int nMasterYAxis;
	int nXAxis;
	int nYAxis;
	//alg v2.0 specific --------
	int nXOffset;//pozitive or negative
	int nYOffset;//pozitive or negative
	bool bIndirectGrowRatioAutomatic;
	//end alg v2.0 specific ----
	float nXGrowthRatio;
	float nYGrowthRatio;
	float nXIndirectGrowthRatio;
	float nYIndirectGrowthRatio;
	CString csText;
	CArray<UINT> canDirectXDependencies;
	CArray<UINT> canDirectYDependencies;
	CArray<CWndProperties *> capDirectXDependencies;	//do not delete !
	CArray<CWndProperties *> capDirectYDependencies;	//do not delete !
	CArray<CWndProperties *> capAllXDependencies;		//do not delete !
	CArray<CWndProperties *> capAllYDependencies;		//do not delete !
	CArray<CWndProperties *> capTemp;					//do not delete !

	CWndProperties();
	CWndProperties(UINT nID);
	CWndProperties(CWndProperties &rX);
	~ CWndProperties();
	void operator=(const CWndProperties &rX);
	bool indirectXDependsBy(CWndProperties * pX);
	bool indirectYDependsBy(CWndProperties * pY);
};


template <class BASECLASS>
class CResizeDlg :
	public BASECLASS
{
	//DECLARE_DYNAMIC(CResizeDlg<BASECLASS>)
public:
	//DECLARE_MESSAGE_MAP()

	//enum { IDD = IDD_BUC_PROGRESS_WND };

public:
	//CResizeDlg(void);
	CResizeDlg(UINT nIDTemplate, CWnd* pParent = NULL);
	virtual ~CResizeDlg(void);
	//virtual BOOL OnInitDialog();

	void setChildExpandable(UINT nID, bool bX = false, bool bY = false);
	void setChildAxesDependencies(UINT nID, UINT nMasterXID, int nXAxis, int nMasterXAxis, UINT nMasterYID, int nYAxis, int nMasterYAxis);
	//alg v2.0 specific --------
	inline void setChildXPosition(UINT nID, UINT nMasterXID, int nXAxis, int nMasterXAxis, int nXOffset = ALIGNMENT_AutoDetectOffset);
	inline void setChildYPosition(UINT nID, UINT nMasterYID, int nYAxis, int nMasterYAxis, int nYOffset = ALIGNMENT_AutoDetectOffset);
	inline void setChildXIndirectGrowthRatio(UINT nID, float nXIndirectGrowthRatio);
	inline void setChildYIndirectGrowthRatio(UINT nID, float nYIndirectGrowthRatio);
	inline void addChildXIndirectGrowthRatio(UINT nID, UINT nMasterID);
	inline void addChildYIndirectGrowthRatio(UINT nID, UINT nMasterID);
	//end alg v2.0 specific ----
	inline void getDefaultWindowAndChildData();
	inline void getWindowType();
	inline void getDefaultWindowSize();
	inline void getDefaultChildWindowsSizeAndPosition();
	CWndProperties * addChildProperties(UINT nID);
	CWndProperties * getChildProperties(UINT nID);
	void prepaireChildrenForResize();
	void deleteChildrenProperties();
	//Nu apela functia asta in OnInitDialog();
	void OnSizeAuto(UINT nType = SIZE_NORESIZE);
	afx_msg void OnSize(UINT nType, int cx, int cy);

protected:
	//virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);

	bool	bIsDerivedFromCScrollView;

	virtual void normalizeDefWindowSize();
	virtual bool getDependencies_onX(CRect c1, CRect c2);
	virtual bool getDependencies_onY(CRect c1, CRect c2);

private:
	CRect _crDefWindowSize;
	int nXOffset;
	int nYOffset;
	CArray<CWndProperties *> _capChildrenProperties;
	CArray<CWndProperties *> _capTemp;					//do not delete !
	CArray<CWndProperties *> _capChildrenPropertiesX;	//do not delete !
	CArray<CWndProperties *> _capChildrenPropertiesY;	//do not delete !

	static BOOL CALLBACK _getChildPositionCallBack(HWND hwnd, LPARAM lParam);
	void _getDirectXYDependencies();
	void _duplicatePropertiesForPointers();
	void _getAllDependenciesX();
	void _getAllDependenciesY();
		bool _mergeLists(CArray<CWndProperties *> &list1, CArray<CWndProperties *> &list2);
		bool _searchPropInList(CArray<CWndProperties *> &rcapDependencies, CWndProperties * pPropToSearch);
		bool _addDependencies_unique(CArray<CWndProperties *> &rcapDependencies, CWndProperties * pPropToBeAdd);
	void _sortPropertiesX();
	void _sortPropertiesY();
		void _sortProperties_XY(CArray<CWndProperties *> &rcapResults);
		void _sortProperties_XY_removeNodeTempGraph(CWndProperties * pNode);
		CWndProperties * _sortProperties_XY_firstIndependentNode();
	void _getGrowthRatioX();
	void _getGrowthRatioY();
	void _invertByDependenciesX();
	void _invertByDependenciesY();

	void _onSize_normalizeSize(UINT nType, int & rcx, int & rcy);
	void _onSize_calculateOffset(UINT nType, int cx, int cy);
	void _onSize_calculateRect(UINT nType, int cx, int cy);
	void _onSize_alignRect(UINT nType, int cx, int cy);
		int _offsetX(CWndProperties * pPropA, CRect & rcrMaster);
		int _offsetY(CWndProperties * pPropA, CRect & rcrMaster);
	void _onSize_applayRect(UINT nType, int cx, int cy);
		int _getDefMinSpaceX(CWndProperties * pProp);
		int _getDefMinSpaceY(CWndProperties * pProp);
		CWndProperties * _getClosestDependencyX(CWndProperties * pProp);
		CWndProperties * _getClosestDependencyY(CWndProperties * pProp);

	void _dbgShowAllDependencies();

	
};

#define INSIDE_OF(x, m, n)   (  ((m<=x)&&(x<=n)) ? (true):(false)  )
#define INTER(a1, a2, b1, b2)  (  (INSIDE_OF(a1, b1, b2) || INSIDE_OF(a2, b1, b2)) ? (true):(false)  )
#define INTERSECT(a1, a2, b1, b2)  (  (INTER(a1, a2, b1, b2) || INTER(b1, b2, a1, a2)) ? (true):(false))



/*template <class BASECLASS>
BEGIN_MESSAGE_MAP(CResizeDlg<BASECLASS>, BASECLASS)
	ON_WM_SIZE()
END_MESSAGE_MAP()*/

//template <class BASECLASS>
//IMPLEMENT_DYNAMIC(CResizeDlg<BASECLASS>, BASECLASS)

/*template <class BASECLASS>
CResizeDlg<BASECLASS>::CResizeDlg(void)
{
	nXOffset = 0;
	nYOffset = 0;
}*/

template <class BASECLASS>
CResizeDlg<BASECLASS>::CResizeDlg(UINT nIDTemplate, CWnd* pParent /*=NULL*/)
	//: BASECLASS(nIDTemplate, pParent)
	: BASECLASS(nIDTemplate)
{
	nXOffset = 0;
	nYOffset = 0;
	bIsDerivedFromCScrollView = false;
}

template <class BASECLASS>
CResizeDlg<BASECLASS>::~CResizeDlg(void)
{
	deleteChildrenProperties();
}


//BOOL CResizeDlg::OnInitDialog()
//{
//	CDialogAsControlBase::OnInitDialog();
//
//
//
//
//	/*
//	//Obs: include this lines in your derived class
//	
//	
//	//get window and child windows information
//	getDefaultWindowAndChildData();
//	
//	//set custom information about child windows
//	setChildExpandable(ctrl_ID1, true, false);
//	setChildExpandable(ctrl_ID2, false, true);
//	setChildExpandable(ctrl_ID3, false, false);
//	...
//
//	//set child windows axes
//	setChildAxesDependencies(ctrl_ID1, 
//		ctrl_ID2, ALIGNMENT_AXIS_1, ALIGNMENT_AXIS_1,
//		0, ALIGNMENT_AXIS_NO, ALIGNMENT_AXIS_NO);
//	setChildAxesDependencies(ctrl_ID3, 
//		ctrl_ID2, ALIGNMENT_AXIS_1, ALIGNMENT_AXIS_3,
//		0, ALIGNMENT_AXIS_NO, ALIGNMENT_AXIS_NO);
//	setChildAxesDependencies(ctrl_ID4, 
//		ctrl_ID2, ALIGNMENT_AXIS_2, ALIGNMENT_AXIS_2,
//		0, ALIGNMENT_AXIS_NO, ALIGNMENT_AXIS_NO);
//	...
//
//	//prepaire the resize alghoritm
//	prepaireChildrenForResize();
//
//	*/
//
//
//
//
//	return TRUE;  // return TRUE unless you set the focus to a control
//	// EXCEPTION: OCX Property Pages should return FALSE
//}



template <class BASECLASS>
void CResizeDlg<BASECLASS>::setChildExpandable(UINT nID, bool bX, bool bY)
{
	CWndProperties * pProp;
	pProp = getChildProperties(nID);
	if (pProp != NULL)
	{
		pProp->bXExpandable = bX;
		pProp->bYExpandable = bY;
	}
}

template <class BASECLASS>
void CResizeDlg<BASECLASS>::setChildAxesDependencies(UINT nID, UINT nMasterXID, int nXAxis, int nMasterXAxis, UINT nMasterYID, int nYAxis, int nMasterYAxis)
{
	CWndProperties * pProp;
	pProp = getChildProperties(nID);
	if (pProp != NULL)
	{
		pProp->wndMasterXID = nMasterXID;
		pProp->wndMasterYID = nMasterYID;
		pProp->nMasterXAxis = nMasterXAxis;
		pProp->nMasterYAxis = nMasterYAxis;
		pProp->nXAxis = nXAxis;
		pProp->nYAxis = nYAxis;
	}
}


////////////////////////////////////////////////////
//alg v2.0 specific --------
//

template <class BASECLASS>
void CResizeDlg<BASECLASS>::setChildXPosition(UINT nID, UINT nMasterXID, int nXAxis, int nMasterXAxis, int nXOffset = 0)
{
	CWndProperties * pProp;
	pProp = getChildProperties(nID);
	if (pProp != NULL)
	{
		pProp->wndMasterXID = nMasterXID;
		pProp->nMasterXAxis = nMasterXAxis;
		pProp->nXAxis = nXAxis;
		pProp->nXOffset = nXOffset;
	}
}

template <class BASECLASS>
void CResizeDlg<BASECLASS>::setChildYPosition(UINT nID, UINT nMasterYID, int nYAxis, int nMasterYAxis, int nYOffset = 0)
{
	CWndProperties * pProp;
	pProp = getChildProperties(nID);
	if (pProp != NULL)
	{
		pProp->wndMasterYID = nMasterYID;
		pProp->nMasterYAxis = nMasterYAxis;
		pProp->nYAxis = nYAxis;
		pProp->nYOffset = nYOffset;
	}
}



template <class BASECLASS>
void CResizeDlg<BASECLASS>::setChildXIndirectGrowthRatio(UINT nID, float nXIndirectGrowthRatio)
{
	CWndProperties * pProp;
	pProp = getChildProperties(nID);
	if (pProp != NULL)
	{
		if (pProp->bIndirectGrowRatioAutomatic == true)
		{
			pProp->nXIndirectGrowthRatio = 0;
			pProp->nYIndirectGrowthRatio = 0;
			pProp->bIndirectGrowRatioAutomatic = false;
		}
		pProp->nXIndirectGrowthRatio += nXIndirectGrowthRatio;
	}
}

template <class BASECLASS>
void CResizeDlg<BASECLASS>::setChildYIndirectGrowthRatio(UINT nID, float nYIndirectGrowthRatio)
{
	CWndProperties * pProp;
	pProp = getChildProperties(nID);
	if (pProp != NULL)
	{
		if (pProp->bIndirectGrowRatioAutomatic == true)
		{
			pProp->nXIndirectGrowthRatio = 0;
			pProp->nYIndirectGrowthRatio = 0;
			pProp->bIndirectGrowRatioAutomatic = false;
		}
		pProp->nYIndirectGrowthRatio += nYIndirectGrowthRatio;
	}
}



template <class BASECLASS>
void CResizeDlg<BASECLASS>::addChildXIndirectGrowthRatio(UINT nID, UINT nMasterID)
{
	CWndProperties * pProp;
	CWndProperties * pMasterProp;
	pProp = getChildProperties(nID);
	pMasterProp = getChildProperties(nMasterID);
	if ((pProp != NULL) && (pMasterProp != NULL))
	{
		if (pProp->bIndirectGrowRatioAutomatic == true)
		{
			pProp->nXIndirectGrowthRatio = 0;
			pProp->nYIndirectGrowthRatio = 0;
			pProp->bIndirectGrowRatioAutomatic = false;
		}
		pProp->nXIndirectGrowthRatio += pMasterProp->nXGrowthRatio;
	}
}

template <class BASECLASS>
void CResizeDlg<BASECLASS>::addChildYIndirectGrowthRatio(UINT nID, UINT nMasterID)
{
	CWndProperties * pProp;
	CWndProperties * pMasterProp;
	pProp = getChildProperties(nID);
	pMasterProp = getChildProperties(nMasterID);
	if ((pProp != NULL) && (pMasterProp != NULL))
	{
		if (pProp->bIndirectGrowRatioAutomatic == true)
		{
			pProp->nXIndirectGrowthRatio = 0;
			pProp->nYIndirectGrowthRatio = 0;
			pProp->bIndirectGrowRatioAutomatic = false;
		}
		pProp->nYIndirectGrowthRatio += pMasterProp->nYGrowthRatio;
	}
}

//
//end alg v2.0 specific ----
////////////////////////////////////////////////////



template <class BASECLASS>
void CResizeDlg<BASECLASS>::getDefaultWindowAndChildData()
{
	getWindowType();
	getDefaultWindowSize();
	getDefaultChildWindowsSizeAndPosition();
}

template <class BASECLASS>
void CResizeDlg<BASECLASS>::getWindowType()
{
/*	CRuntimeClass * pC1 = NULL, * pC2 = NULL;
	CScrollView * pScrollView = NULL;
	
	pC1 = RUNTIME_CLASS(BASECLASS);
	pC2 = RUNTIME_CLASS(CScrollView);
	if (pC1->IsDerivedFrom(pC2) == TRUE)
	{
		bIsDerivedFromCScrollView = true;
	} else {
		bIsDerivedFromCScrollView = false;
	}*/
	bIsDerivedFromCScrollView = false;
}

template <class BASECLASS>
void CResizeDlg<BASECLASS>::getDefaultWindowSize()
{
	GetClientRect(& _crDefWindowSize);

	if (bIsDerivedFromCScrollView)
	{
		//SCROLLBARINFO sbi;
		int nMapMode = MM_TEXT;
		CSize sizeTotal, sizePage, sizeLine;

		((CScrollView*)this)->GetDeviceScrollSizes(nMapMode, sizeTotal, sizePage, sizeLine);

		//sbi.cbSize = sizeof(sbi);
		//GetScrollBarInfo(OBJID_VSCROLL, &sbi);
		//if (GetScrollBarInfo(OBJID_VSCROLL, &sbi) && !(sbi.rgstate[0] & (STATE_SYSTEM_INVISIBLE | STATE_SYSTEM_OFFSCREEN | STATE_SYSTEM_UNAVAILABLE)))
		{
			_crDefWindowSize.bottom = sizeTotal.cy;
		}
		//if (GetScrollBarInfo(OBJID_HSCROLL, &sbi) && !(sbi.rgstate[0] & (STATE_SYSTEM_INVISIBLE | STATE_SYSTEM_OFFSCREEN | STATE_SYSTEM_UNAVAILABLE)))
		{
			_crDefWindowSize.right = sizeTotal.cx;
		}
	}
	normalizeDefWindowSize();
}

template <class BASECLASS>
void CResizeDlg<BASECLASS>::getDefaultChildWindowsSizeAndPosition()
{
	HWND hwnd;
	hwnd = GetSafeHwnd();
	::EnumChildWindows(hwnd, _getChildPositionCallBack, (LPARAM)this);
}

template <class BASECLASS>
CWndProperties * CResizeDlg<BASECLASS>::addChildProperties(UINT nID)
{
	CWndProperties * pProp;
	pProp = getChildProperties(nID);
	if (pProp != NULL)
	{
		return pProp;
	}
	pProp = new CWndProperties(nID);
	_capChildrenProperties.Add(pProp);
	return pProp;
}

template <class BASECLASS>
CWndProperties * CResizeDlg<BASECLASS>::getChildProperties(UINT nID)
{
	INT_PTR i, n;
	CWndProperties * pProp;
	n = _capChildrenProperties.GetCount();
	for(i=0; i<n; i++)
	{
		pProp = _capChildrenProperties[i];
		if (pProp->wndID == nID)
		{
			return pProp;
		}
	}
	return NULL;
}

template <class BASECLASS>
void CResizeDlg<BASECLASS>::prepaireChildrenForResize()
{
	_getDirectXYDependencies();
	_duplicatePropertiesForPointers();

	_getAllDependenciesX();
	_getAllDependenciesY();
	
	_sortPropertiesX();
	_sortPropertiesY();
	
	_getGrowthRatioX();
	_getGrowthRatioY();

	_invertByDependenciesX();
	_invertByDependenciesY();

	//_dbgShowAllDependencies();
}

template <class BASECLASS>
void CResizeDlg<BASECLASS>::deleteChildrenProperties()
{
	INT_PTR i, n;
	n = _capChildrenProperties.GetCount();
	for(i=0; i<n; i++)
	{
		delete _capChildrenProperties[i];
	}
	_capChildrenProperties.RemoveAll();
	_capChildrenPropertiesX.RemoveAll();
	_capChildrenPropertiesY.RemoveAll();
}

//Este folosita pentru a reordona controalele ferestrei.
//
//Atentie: Nu apela functia asta in OnInitDialog();
//
template <class BASECLASS>
void CResizeDlg<BASECLASS>::OnSizeAuto(UINT nType)
{
	CRect rect;

	GetClientRect(& rect);

	OnSize(nType, rect.Width(), rect.Height());
	Invalidate();
}


//template <class BASECLASS>
//LRESULT CResizeDlg<BASECLASS>::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
//{
//	LRESULT lResult = BASECLASS::WindowProc(message, wParam, lParam);
//	if (message == WM_SIZE)
//	{
//		int cx = LOWORD(lParam), cy = HIWORD(lParam);
//		onSize_preCalculateRect((UINT)wParam, cx, cy);
//		_onSize_calculateRect((UINT)wParam, cx, cy);
//		onSize_preAlignRect((UINT)wParam, cx, cy);
//		_onSize_alignRect((UINT)wParam, cx, cy);
//		onSize_preApplayRect((UINT)wParam, cx, cy);
//		_onSize_applayRect((UINT)wParam, cx, cy);
//	}
//	return lResult;
//}

template <class BASECLASS>
void CResizeDlg<BASECLASS>::OnSize(UINT nType, int cx, int cy)
{
	if (nType != SIZE_NORESIZE)
	{
		BASECLASS::OnSize(nType, cx, cy);
	}

	if (_capChildrenProperties.GetCount())
	{
		_onSize_normalizeSize(nType, cx, cy);
		_onSize_calculateOffset(nType, cx, cy);
		_onSize_calculateRect(nType, cx, cy);
		_onSize_alignRect(nType, cx, cy);
		_onSize_applayRect(nType, cx, cy);
	}
}




template <class BASECLASS>
void CResizeDlg<BASECLASS>::normalizeDefWindowSize()
{
}


template <class BASECLASS>
bool CResizeDlg<BASECLASS>::getDependencies_onX(CRect c1, CRect c2)
{
	if (c2.right < c1.left)
	{
		return true;
	}
	return false;
}



template <class BASECLASS>
bool CResizeDlg<BASECLASS>::getDependencies_onY(CRect c1, CRect c2)
{
	if (c2.bottom < c1.top)
	{
		return true;
	}
	return false;
}





template <class BASECLASS>
BOOL CALLBACK CResizeDlg<BASECLASS>::_getChildPositionCallBack(HWND hwnd, LPARAM lParam)
{
	CResizeDlg<BASECLASS> * pParent;
	HWND hParent;
	UINT nID;
	CRect crRect;
	CWndProperties * pProp;
	CString csDebug;
	wchar_t pwcChild[100];

	pParent = (CResizeDlg<BASECLASS> *) lParam;
	hParent = pParent->GetSafeHwnd();
	if (::GetParent(hwnd) == hParent)
	{
		::GetWindowRect(hwnd, &crRect);
		pParent->ScreenToClient(&crRect);
		nID = ::GetDlgCtrlID(hwnd);
		pProp = pParent->addChildProperties(nID);
		pProp->crDefPosition = crRect;
		

		//::GetWindowText(hParent, pwcParent, 100);
		//::GetWindowText(hwnd, pwcChild, 100);
/*
		csDebug.Format(_T("%s: %s (id=%d) [(%d,%d)(%d,%d)]\r\n"),
			pwcParent,
			pwcChild,
			nID,
			crRect.left, crRect.top,
			crRect.right, crRect.bottom);
		TRACE(csDebug.GetBuffer());*/


		pProp->csText = pwcChild;
	}
	
	return TRUE;
}

template <class BASECLASS>
void CResizeDlg<BASECLASS>::_getDirectXYDependencies()
{
	INT_PTR i, j, n;
	CWndProperties * pProp;
	CWndProperties * pPropCursor;

	//for all child windows
	n = _capChildrenProperties.GetCount();
	for(i=0; i<n; i++)
	{
		pProp = _capChildrenProperties[i];
		//for all child windows
		for(j=0; j<n; j++)
		{
			pPropCursor = _capChildrenProperties[j];
			//except the current one
			if(pProp != pPropCursor)
			{
				if (getDependencies_onX(pProp->crDefPosition, pPropCursor->crDefPosition) == true)
				{
					pProp->capDirectXDependencies.Add(pPropCursor);
				}

				if (getDependencies_onY(pProp->crDefPosition, pPropCursor->crDefPosition) == true)
				{
					pProp->capDirectYDependencies.Add(pPropCursor);
				}
			}
		}
	}
}

template <class BASECLASS>
void CResizeDlg<BASECLASS>::_duplicatePropertiesForPointers()
{
	INT_PTR i, n;
	INT_PTR j, m;
	UINT nID;
	CWndProperties * pProp;
	CWndProperties * pDep;

	//for al properties
	n = _capChildrenProperties.GetCount();
	for(i=0; i<n; i++)
	{
		pProp = _capChildrenProperties[i];
		//duplicate x dependencies by pointers using IDs
		m = pProp->canDirectXDependencies.GetCount();
		for(j=0; j<m; j++)
		{
			nID = pProp->canDirectXDependencies[i];
			pDep = getChildProperties(nID);
			if (pDep != NULL)
			{
				pProp->capDirectXDependencies.Add(pDep);
			}
		}
		//duplicate y dependencies by pointers using IDs
		m = pProp->canDirectYDependencies.GetCount();
		for(j=0; j<m; j++)
		{
			nID = pProp->canDirectYDependencies[i];
			pDep = getChildProperties(nID);
			if (pDep != NULL)
			{
				pProp->capDirectYDependencies.Add(pDep);
			}
		}
	}
}

template <class BASECLASS>
void CResizeDlg<BASECLASS>::_getAllDependenciesX()
{
	INT_PTR i, n;
	INT_PTR j, m;
	CWndProperties * pCurrent;
	CWndProperties * pCursor;
	bool bFound;

	//_dbgShowAllDependencies();
	
	//
	//Step1:
	//
	//copy direct dependencies to indirect dependencies list
	//
	n = _capChildrenProperties.GetCount();
	for(i=0; i<n; i++)
	{
		pCurrent = _capChildrenProperties[i];
		pCurrent->capAllXDependencies.Copy( pCurrent->capDirectXDependencies );
	}


	//
	//Step2:
	//
	//add all dependencies from all dependencies to all dependencies list
	//while some list was appdated
	//
	bFound = true;
	n = _capChildrenProperties.GetCount();
	do
	{
		bFound = false;
		//for properties
		for(i=0; i<n; i++)
		{
			pCurrent = _capChildrenProperties[i];
			//for its dependencies
			m = pCurrent->capAllXDependencies.GetCount();
			for(j=0; j<m; j++)
			{
				//merge list of dependends
				pCursor = pCurrent->capAllXDependencies[j];
				if (_mergeLists(pCurrent->capAllXDependencies, pCursor->capAllXDependencies) == true)
				{
					//at list one dependent added
					bFound = true;
					//the list is bigger
					m = pCurrent->capAllXDependencies.GetCount();
				}
			}
		}
	}while (bFound == true);


	//_dbgShowAllDependencies();

}

template <class BASECLASS>
void CResizeDlg<BASECLASS>::_getAllDependenciesY()
{
	INT_PTR i, n;
	INT_PTR j, m;
	CWndProperties * pCurrent;
	CWndProperties * pCursor;
	bool bFound;

	//_dbgShowAllDependencies();
	
	//
	//Step1:
	//
	//copy direct dependencies to indirect dependencies list
	//
	n = _capChildrenProperties.GetCount();
	for(i=0; i<n; i++)
	{
		pCurrent = _capChildrenProperties[i];
		pCurrent->capAllYDependencies.Copy( pCurrent->capDirectYDependencies );
	}


	//
	//Step2:
	//
	//add all dependencies from all dependencies to all dependencies list
	//while some list was appdated
	//
	bFound = true;
	n = _capChildrenProperties.GetCount();
	do
	{
		bFound = false;
		//for properties
		for(i=0; i<n; i++)
		{
			pCurrent = _capChildrenProperties[i];
			//for its dependencies
			m = pCurrent->capAllYDependencies.GetCount();
			for(j=0; j<m; j++)
			{
				//merge list of dependends
				pCursor = pCurrent->capAllYDependencies[j];
				if (_mergeLists(pCurrent->capAllYDependencies, pCursor->capAllYDependencies) == true)
				{
					//at list one dependent added
					bFound = true;
					//the list is bigger
					m = pCurrent->capAllYDependencies.GetCount();
				}
			}
		}
	}while (bFound == true);


	//_dbgShowAllDependencies();
}


//second list is copied at the end of the first list in unique mode
//(no duplicates values permitted)
//
//return true if at least one new value added
//return false if first list is the same
template <class BASECLASS>
bool CResizeDlg<BASECLASS>::_mergeLists(CArray<CWndProperties *> &list1, CArray<CWndProperties *> &list2)
{
	INT_PTR i, n;
	CWndProperties * pToBeAdded;
	bool bNewValueAdded;
	n = list2.GetCount();
	bNewValueAdded = false;
	for(i=0; i<n; i++)
	{
		pToBeAdded = list2[i];
		if (_addDependencies_unique(list1, pToBeAdded) == true)
		{
			bNewValueAdded = true;
		}
	}

	return bNewValueAdded;
}

template <class BASECLASS>
bool CResizeDlg<BASECLASS>::_searchPropInList(CArray<CWndProperties *> &rcapDependencies, CWndProperties * pPropToSearch)
{
	INT_PTR i, n;
	CWndProperties * pInList;
	n = rcapDependencies.GetCount();
	for(i=0; i<n; i++)
	{
		pInList = rcapDependencies[i];
		if (pInList == pPropToSearch)
		{
			return true;
		}
	}
	return false;
}


//return true if the value has been added
//return false if the value was already in list
template <class BASECLASS>
bool CResizeDlg<BASECLASS>::_addDependencies_unique(CArray<CWndProperties *> &rcapDependencies, CWndProperties * pPropToBeAdd)
{
	if (_searchPropInList(rcapDependencies, pPropToBeAdd) == false)
	{
		rcapDependencies.Add(pPropToBeAdd);
		return true;
	}
	return false;
}


template <class BASECLASS>
void CResizeDlg<BASECLASS>::_sortPropertiesX()
{
	INT_PTR i, n;
	CWndProperties * pProp;

	//
	//Step 1:
	//
	//create a temporary dependency graph based on x dependencies
	//
	n = _capChildrenProperties.GetCount();
	for(i=0; i<n; i++)
	{
		pProp = _capChildrenProperties[i];
		pProp->capTemp.Copy( pProp->capDirectXDependencies );
	}
	_capTemp.Copy( _capChildrenProperties );

	//
	//Step 2:
	//
	//run the algorithm storing the results into x calculation order array
	//
	_sortProperties_XY(_capChildrenPropertiesX);


	//
	//Step 3:
	//
	//remove the temporary graph
	//
	n = _capChildrenProperties.GetCount();
	for(i=0; i<n; i++)
	{
		pProp = _capChildrenProperties[i];
		pProp->capTemp.RemoveAll();
	}
	_capTemp.RemoveAll();

}

template <class BASECLASS>
void CResizeDlg<BASECLASS>::_sortPropertiesY()
{
	INT_PTR i, n;
	CWndProperties * pProp;

	//
	//Step 1:
	//
	//create a temporary dependency graph based on y dependencies
	//
	n = _capChildrenProperties.GetCount();
	for(i=0; i<n; i++)
	{
		pProp = _capChildrenProperties[i];
		pProp->capTemp.Copy( pProp->capDirectYDependencies );
	}
	_capTemp.Copy( _capChildrenProperties );

	//
	//Step 2:
	//
	//run the algorithm storing the results into y calculation order array
	//
	_sortProperties_XY(_capChildrenPropertiesY);


	//
	//Step 3:
	//
	//remove the temporary graph
	//
	n = _capChildrenProperties.GetCount();
	for(i=0; i<n; i++)
	{
		pProp = _capChildrenProperties[i];
		pProp->capTemp.RemoveAll();
	}
	_capTemp.RemoveAll();
}



template <class BASECLASS>
void CResizeDlg<BASECLASS>::_sortProperties_XY(CArray<CWndProperties *> &rcapResults)
{
	CWndProperties * pProp;

	//get the first independent node
	pProp = _sortProperties_XY_firstIndependentNode();
	while (pProp != NULL)
	{
		//store the node in result array
		rcapResults.Add( pProp );

		//remove the node from temporary graph
		_sortProperties_XY_removeNodeTempGraph( pProp );

		//next independend node
		pProp = _sortProperties_XY_firstIndependentNode();
	}
}


template <class BASECLASS>
void CResizeDlg<BASECLASS>::_sortProperties_XY_removeNodeTempGraph(CWndProperties * pNode)
{
	INT_PTR i, n;
	CWndProperties * pProp;
	INT_PTR j, m;
	CWndProperties * pLink;

	//for all nodes in the graph
	n = _capTemp.GetCount();
	for(i=0; i<n; i++)
	{
		pProp = _capTemp[i];
		
		//for all links of the current node
		m = pProp->capTemp.GetCount();
		for(j=0; j<m; j++)
		{
			pLink = pProp->capTemp[j];

			//if a link was fond between current node and the node to be removed
			if (pLink == pNode)
			{
				//remove the link
				pProp->capTemp.RemoveAt(j);
				m = pProp->capTemp.GetCount();
				j = 0;
			}
		}
	}

	//remove the node from temp list
	n = _capTemp.GetCount();
	for(i=0; i<n; i++)
	{
		pProp = _capTemp[i];
		if (pProp == pNode)
		{
			_capTemp.RemoveAt(i);
			break;
		}
	}
}


template <class BASECLASS>
CWndProperties * CResizeDlg<BASECLASS>::_sortProperties_XY_firstIndependentNode()
{
	INT_PTR i, n;
	CWndProperties * pCurrent = NULL;

	//test all nodes to find an independend one
	n = _capTemp.GetCount();
	for(i=0; i<n; i++)
	{
		pCurrent = _capTemp[i];

		//if the current node is independent
		if (pCurrent->capTemp.GetCount() == 0)
		{
			return pCurrent;
		}
	}

	return NULL;
}



//calculate growth ratio by x for all windows
//
template <class BASECLASS>
void CResizeDlg<BASECLASS>::_getGrowthRatioX()
{


	//
	// Old version (buggy because the fixed-width windows)
	//
	/*
	CWndProperties * pProp;
	INT_PTR i, n;
	int defDim;
	int defWndDim;

	n = _capChildrenPropertiesX.GetCount();
	defWndDim = _crDefWindowSize.right - _crDefWindowSize.left;
	for(i=0; i<n; i++)
	{
		pProp = _capChildrenPropertiesX[i];
		defDim = pProp->crDefPosition.right - pProp->crDefPosition.left;
		pProp->nXGrowthRatio = ((float)defDim)/((float)defWndDim);
	}
	*/




	//
	// New version (better because fixed-width is redistributed to variable-width windows)
	//
	INT_PTR i, k, n;
	CWndProperties * pCurrentProp;
	CWndProperties * pProp;
	int nMaxWindowDefSize = _crDefWindowSize.Width();
	int nWindowPixelArray[5000];
	int j;
	int nPlaceToBeMarked;
	int nValueToBeMarked;
	int nTotalFixedWidth;
	int defDim;
	int defWndDim;
	float f;
	int nVariableWidth;

	//calculate growth ratio for all child windows
	n = _capChildrenPropertiesX.GetCount();
	for(k=0; k<n; k++)
	{
		pCurrentProp = _capChildrenPropertiesX[k];

		//clear the array
		for(j=0; j<nMaxWindowDefSize; j++)
		{
			nWindowPixelArray[j] = 0;
		}

		//mark maximum fixed width looking in all child windows
		for(i=0; i<n; i++)
		{
			pProp = _capChildrenPropertiesX[i];

			//if child windows are dependable
			if ((pCurrentProp->indirectXDependsBy(pProp) == true) ||
				(pProp->indirectXDependsBy(pCurrentProp) == true))
			{
				nPlaceToBeMarked = pProp->crDefPosition.left;
				nValueToBeMarked = pProp->crDefPosition.Width();
				//if the place is in window array
				if ((nPlaceToBeMarked >= 0) && (nPlaceToBeMarked < nMaxWindowDefSize))
				{
					//if child window has a fixed width
					if (pProp->bXExpandable == false)
					{
						for(j=nPlaceToBeMarked; j<nPlaceToBeMarked+nValueToBeMarked; j++)
						{
							if (nWindowPixelArray[j] != -1) nWindowPixelArray[j] = 1;
						}
					} else
					{
						for(j=nPlaceToBeMarked; j<nPlaceToBeMarked+nValueToBeMarked; j++)
						{
							nWindowPixelArray[j] = -1;
						}
					}
				}
			}
		}


		//gather total real fixed-width
		nTotalFixedWidth = 0;
		nVariableWidth = 0;
		for(j=0; j<nMaxWindowDefSize; j++)
		{
			//real space and non expandable windows
			if ((nWindowPixelArray[j] == 0) || (nWindowPixelArray[j] == 1))
			{
				//summ
				nTotalFixedWidth++;
			}
			//windows with variable size
			if (nWindowPixelArray[j] == -1)
			{
				//sum
				nVariableWidth++;
			}
		}

		//current window is viewed as a space
		nTotalFixedWidth = nTotalFixedWidth - pCurrentProp->crDefPosition.Width();

		//if the window is not the only one resizeable, the indirect grow ratio must be
		//distributed among all of them
		f = (float)pCurrentProp->crDefPosition.Width() / (float)(nVariableWidth + pCurrentProp->crDefPosition.Width());

		
		//calculate ratio
		defWndDim = _crDefWindowSize.Width();
		defDim = pCurrentProp->crDefPosition.Width();
		//pCurrentProp->nXGrowthRatio = (float)defDim/((float)defWndDim + 14);
		//pCurrentProp->nXIndirectGrowthRatio = (float)nTotalFixedWidth/((float)defWndDim + 14);
		pCurrentProp->nXGrowthRatio = (float)defDim/((float)defWndDim);
		pCurrentProp->nXIndirectGrowthRatio = f * (float)nTotalFixedWidth/((float)defWndDim);
		pCurrentProp->bIndirectGrowRatioAutomatic = true;

	}

}



//calculate growth ratio by y for all windows
//
template <class BASECLASS>
void CResizeDlg<BASECLASS>::_getGrowthRatioY()
{
	
	//
	// Old version (buggy because the fixed-hight windows)
	//
	/*
	CWndProperties * pProp;
	INT_PTR i, n;
	int defDim;
	int defWndDim;

	n = _capChildrenPropertiesY.GetCount();
	defWndDim = _crDefWindowSize.Height();
	for(i=0; i<n; i++)
	{
		pProp = _capChildrenPropertiesY[i];
		defDim = pProp->crDefPosition.Height();
		pProp->nYGrowthRatio = ((float)defDim)/((float)defWndDim);
	}
	*/



	//
	// New version (better because fixed-hight is redistributed to variable-height windows)
	//
	INT_PTR i, k, n;
	CWndProperties * pCurrentProp;
	CWndProperties * pProp;
	int nMaxWindowDefSize = _crDefWindowSize.Height();
	int nWindowPixelArray[5000];
	int j;
	int nPlaceToBeMarked;
	int nValueToBeMarked;
	int nTotalFixedHeight;
	int defDim;
	int defWndDim;
	float f;
	int nVariableHeight;

	//calculate growth ratio for all child windows
	n = _capChildrenPropertiesY.GetCount();
	for(k=0; k<n; k++)
	{
		pCurrentProp = _capChildrenPropertiesY[k];

		//clear the array
		for(j=0; j<nMaxWindowDefSize; j++)
		{
			nWindowPixelArray[j] = 0;
		}

		//mark maximum fixed heigh looking in all child windows
		for(i=0; i<n; i++)
		{
			pProp = _capChildrenPropertiesY[i];

			//if child windows are dependable
			if ((pCurrentProp->indirectYDependsBy(pProp) == true) ||
				(pProp->indirectYDependsBy(pCurrentProp) == true))
			{
				nPlaceToBeMarked = pProp->crDefPosition.top;
				nValueToBeMarked = pProp->crDefPosition.Height();
				//if the place is in window array
				if ((nPlaceToBeMarked >= 0) && (nPlaceToBeMarked < nMaxWindowDefSize))
				{
					//if child window has a fixed width
					if (pProp->bYExpandable == false)
					{
						for(j=nPlaceToBeMarked; j<nPlaceToBeMarked+nValueToBeMarked; j++)
						{
							if (nWindowPixelArray[j] != -1) nWindowPixelArray[j] = 1;
						}
					} else
					{
						for(j=nPlaceToBeMarked; j<nPlaceToBeMarked+nValueToBeMarked; j++)
						{
							nWindowPixelArray[j] = -1;
						}
					}
				}
			}
		}

		//gather total real fixed-width
		nTotalFixedHeight = 0;
		nVariableHeight = 0;
		for(j=0; j<nMaxWindowDefSize; j++)
		{
			//real space and non expandable windows
			if ((nWindowPixelArray[j] == 0) || (nWindowPixelArray[j] == 1))
			{
				//summ
				nTotalFixedHeight++;
			}
			//windows with variable size
			if (nWindowPixelArray[j] == -1)
			{
				//sum
				nVariableHeight++;
			}
		}

		//current window is viewed as a space
		nTotalFixedHeight = nTotalFixedHeight - pCurrentProp->crDefPosition.Height();

		//if the window is not the only one resizeable, the indirect grow ratio must be
		//distributed among all of them
		f = (float)pCurrentProp->crDefPosition.Height() / (float)(nVariableHeight + pCurrentProp->crDefPosition.Height());

		
		//calculate ratio
		defWndDim = _crDefWindowSize.Height();
		defDim = pCurrentProp->crDefPosition.Height();
		//pCurrentProp->nYGrowthRatio = (float)defDim/((float)defWndDim + 14);
		//pCurrentProp->nYIndirectGrowthRatio = (float)nTotalFixedHeight/((float)defWndDim + 14);
		pCurrentProp->nYGrowthRatio = (float)defDim/((float)defWndDim);
		pCurrentProp->nYIndirectGrowthRatio =  f * (float)nTotalFixedHeight/((float)defWndDim);
		pCurrentProp->bIndirectGrowRatioAutomatic = true;
	}

}

//if B control depends by A control and the automatic dependencies searching algorithm finds the thow
//controls as A depends by B, then this function will correct the order in dependencies list
//
template <class BASECLASS>
void CResizeDlg<BASECLASS>::_invertByDependenciesX()
{
	INT_PTR i, j, n;
	CWndProperties * pPropA = NULL;
	CWndProperties * pPropB = NULL;
	bool bChange;
	int k;

	n = _capChildrenPropertiesX.GetCount();
	bChange = true;
	k = 0;
	while ((bChange == true) && (k < 10))
	{
		bChange = false;
		for(i=0; i<n-1; i++)
		{
			pPropA = _capChildrenPropertiesX[i];
			for(j=i+1; j<n; j++)
			{
				pPropB = _capChildrenPropertiesX[j];
				if (pPropA->wndMasterXID == pPropB->wndID)
				{
					if (pPropB->wndMasterXID != pPropA->wndID)
					{
						_capChildrenPropertiesX.SetAt(i, pPropB);
						_capChildrenPropertiesX.SetAt(j, pPropA);
						bChange = true;
					} else
					{
						TRACE(_T("\r\nWindow cotrols dependencies -> direct cycle!\r\n"));
					}
				}
			}
		}

		k++;
	}

	if (k == 10)
	{
		TRACE(_T("\r\nWindow cotrols dependencies -> possible indirect cycle!\r\n"));
	}
}


//if B control depends by A control and the automatic dependencies searching algorithm finds the thow
//controls as A depends by B, then this function will correct the order in dependencies list
//
template <class BASECLASS>
void CResizeDlg<BASECLASS>::_invertByDependenciesY()
{
	INT_PTR i, j, n;
	CWndProperties * pPropA = NULL;
	CWndProperties * pPropB = NULL;
	bool bChange;
	int k;

	n = _capChildrenPropertiesY.GetCount();
	bChange = true;
	k = 0;
	while ((bChange == true) && (k < 10))
	{
		bChange = false;
		for(i=0; i<n-1; i++)
		{
			pPropA = _capChildrenPropertiesY[i];
			for(j=i+1; j<n; j++)
			{
				pPropB = _capChildrenPropertiesY[j];
				if (pPropA->wndMasterYID == pPropB->wndID)
				{
					if (pPropB->wndMasterYID != pPropA->wndID)
					{
						_capChildrenPropertiesY.SetAt(i, pPropB);
						_capChildrenPropertiesY.SetAt(j, pPropA);
						bChange = true;
					} else
					{
						TRACE(_T("\r\nWindow cotrols dependencies -> direct cycle!\r\n"));
					}
				}
			}
		}

		k++;
	}

	if (k == 10)
	{
		TRACE(_T("\r\nWindow cotrols dependencies -> possible indirect cycle!\r\n"));
	}
}



//look for the minimum distance between pProp and one of all its dependencies
//
//return -1 if no space detected (independent window)
//
template <class BASECLASS>
int CResizeDlg<BASECLASS>::_getDefMinSpaceX(CWndProperties * pProp)
{
	INT_PTR i, n;
	CWndProperties * pCursor = NULL;
	int nSpace = -1;
	int nNewSpace;

	n = pProp->capAllXDependencies.GetCount();
	for(i=0; i<n; i++)
	{
		pCursor = pProp->capAllXDependencies[i];
		nNewSpace = pProp->crDefPosition.left - pCursor->crDefPosition.right;
		if (nSpace == -1)
		{
			nSpace = nNewSpace;
		}
		else
		{
			if (nNewSpace < nSpace)
			{
				nSpace = nNewSpace;
			}
		}
	}

	return nSpace;
}


//look for the minimum distance between pProp and one of all its dependencies
//
//return -1 if no space detected (independent window)
//
template <class BASECLASS>
int CResizeDlg<BASECLASS>::_getDefMinSpaceY(CWndProperties * pProp)
{
	INT_PTR i, n;
	CWndProperties * pCursor = NULL;
	int nSpace = -1;
	int nNewSpace;

	n = pProp->capAllYDependencies.GetCount();
	for(i=0; i<n; i++)
	{
		pCursor = pProp->capAllYDependencies[i];
		nNewSpace = pProp->crDefPosition.top - pCursor->crDefPosition.bottom;
		if (nSpace == -1)
		{
			nSpace = nNewSpace;
		}
		else
		{
			if (nNewSpace < nSpace)
			{
				nSpace = nNewSpace;
			}
		}
	}

	return nSpace;
}


//look for the closest window in dependencies list
//
//return NULL if none found
//
template <class BASECLASS>
CWndProperties * CResizeDlg<BASECLASS>::_getClosestDependencyX(CWndProperties * pProp)
{
	INT_PTR i, n;
	CWndProperties * pCursor = NULL;
	int nX = -1;
	CWndProperties * pClose = NULL;

	n = pProp->capAllXDependencies.GetCount();
	for(i=0; i<n; i++)
	{
		pCursor = pProp->capAllXDependencies[i];
		if (nX == -1)
		{
			nX = pCursor->crPosition.right;
			pClose = pCursor;
		}
		else
		{
			if (nX < pCursor->crPosition.right)
			{
				nX = pCursor->crPosition.right;
				pClose = pCursor;
			}
		}
	}

	return pClose;
}


//look for the closest window in dependencies list
//
//return NULL if none found
//
template <class BASECLASS>
CWndProperties * CResizeDlg<BASECLASS>::_getClosestDependencyY(CWndProperties * pProp)
{
	INT_PTR i, n;
	CWndProperties * pCursor = NULL;
	int nX = -1;
	CWndProperties * pClose = NULL;

	n = pProp->capAllYDependencies.GetCount();
	for(i=0; i<n; i++)
	{
		pCursor = pProp->capAllYDependencies[i];
		if (nX == -1)
		{
			nX = pCursor->crPosition.bottom;
			pClose = pCursor;
		}
		else
		{
			if (nX < pCursor->crPosition.bottom)
			{
				nX = pCursor->crPosition.bottom;
				pClose = pCursor;
			}
		}
	}

	return pClose;
}



template <class BASECLASS>
void CResizeDlg<BASECLASS>::_onSize_normalizeSize(UINT nType, int & rcx, int & rcy)
{
	//CRuntimeClass * pC1 = NULL, * pC2 = NULL;
	//CScrollView * pScrollView = NULL;
	//CPoint cp;

	//int nMapMode;
	//SIZE sizeTotal;
	//SIZE sizePage;
	//SIZE sizeLine;

	//SIZE sizeTotal2;

	//BOOL bHasHorzBar;
	//BOOL bHasVertBar;

	//
	//pC1 = RUNTIME_CLASS(BASECLASS);
	//pC2 = RUNTIME_CLASS(CScrollView);
	//if (pC1->IsDerivedFrom(pC2) == TRUE)
	//{
		//pScrollView = (CScrollView *) this;
		//cp = pScrollView->GetDeviceScrollPosition();	

		////---
		//sizeTotal2 = pScrollView->GetTotalSize();
		//pScrollView->GetDeviceScrollSizes(nMapMode, sizeTotal, sizePage, sizeLine);
		//pScrollView->CheckScrollBars(bHasHorzBar, bHasVertBar);
		//CString a;
		//a.Format(_T("sizeTotal=%d; sizeTotal=%d; bHasHorzBar=%d; bHasVertBar=%d; cp.x=%LX; cp.y=%LX\n", sizeTotal, sizeTotal2, bHasHorzBar, bHasVertBar, (int)cp.x, (int)cp.y);
		//TRACE(a);

		//CRect rcClient;
		//GetClientRect(& rcClient);
		//a.Format(_T("rcClient.Width=%d; rcClient.Height=%d; rcx=%d; rcy=%d;\n", rcClient.Width(), rcClient.Height(), rcx, rcy);
		//TRACE(a);
		////---

		//CScrollBar * pHScrollBar = this->GetScrollBarCtrl(SB_HORZ);
		//CScrollBar * pVScrollBar = this->GetScrollBarCtrl(SB_VERT);


	//	if (rcx < this->_crDefWindowSize.Width())
	//	{
	//		rcx = this->_crDefWindowSize.Width();
	//	}
	//	if (rcy < this->_crDefWindowSize.Height())
	//	{
	//		rcy = this->_crDefWindowSize.Height();
	//	}

	//}


	

	if (bIsDerivedFromCScrollView == true)
	{
		//int nMapMode = MM_TEXT;
		//CSize sizeTotal, sizePage, sizeLine;

		//((CScrollView*)this)->GetDeviceScrollSizes(nMapMode, sizeTotal, sizePage, sizeLine);

		if (rcx < _crDefWindowSize.Width())
		{
			rcx = _crDefWindowSize.Width();
		}
		if (rcy < _crDefWindowSize.Height())
		{
			rcy = _crDefWindowSize.Height();
		}

		//if (rcx < this->_crDefWindowSize.Width())
		//{
		//	rcx = this->_crDefWindowSize.Width();
		//}
		//if (rcy < this->_crDefWindowSize.Height())
		//{
		//	rcy = this->_crDefWindowSize.Height();
		//}
	}



}


template <class BASECLASS>
void CResizeDlg<BASECLASS>::_onSize_calculateOffset(UINT nType, int cx, int cy)
{
	//CRuntimeClass * pC1 = NULL, * pC2 = NULL;
	CScrollView * pScrollView = NULL;
	CPoint cp;

	//pC1 = RUNTIME_CLASS(BASECLASS);
	//pC2 = RUNTIME_CLASS(CScrollView);
	//if (pC1->IsDerivedFrom(pC2) == TRUE)
	if (bIsDerivedFromCScrollView == true)
	{
		pScrollView = (CScrollView *) this;
		cp = pScrollView->GetDeviceScrollPosition();
		nXOffset = -cp.x;
		nYOffset = -cp.y;

	} else
	{
		nXOffset = 0;
		nYOffset = 0;
	}


}


template <class BASECLASS>
void CResizeDlg<BASECLASS>::_onSize_calculateRect(UINT nType, int cx, int cy)
{
	INT_PTR i, n;
	CWndProperties * pProp;
	CWnd *pWnd = NULL;
	//int dim;
	//int space;
	//CWndProperties * pCloseDep;


	////
	////calculating X
	////
	//n = _capChildrenPropertiesX.GetCount();
	//for(i=0; i<n; i++)
	//{
	//	pProp = _capChildrenPropertiesX[i];
	//	pProp->crPosition.left = 0;
	//	pProp->crPosition.right = 0;

	//	////calculating width
	//	//if (pProp->bXExpandable == true)
	//	//{
	//	//	pProp->crPosition.right = (int)(cx * pProp->nXGrowthRatio);
	//	//} else
	//	//{
	//	//	pProp->crPosition.right = pProp->crDefPosition.Width();
	//	//}

	//	////calculating position
	//	//space = _getDefMinSpaceX(pProp);
	//	//if (space < 0)
	//	//{
	//	//	pProp->crPosition.MoveToX(pProp->crDefPosition.left);
	//	//}
	//	//if (space >= 0)
	//	//{
	//	//	//space = space * cx / defWndDim;
	//	//	pCloseDep = _getClosestDependencyX(pProp);
	//	//	if (pCloseDep == NULL)
	//	//	{
	//	//		pProp->crPosition.MoveToX(pProp->crDefPosition.left);
	//	//	}
	//	//	if (pCloseDep != NULL)
	//	//	{
	//	//		pProp->crPosition.MoveToX(pCloseDep->crPosition.right + space);
	//	//	}
	//	//}


	//	//alg v2.0 specific --------
	//	if (pProp->bXExpandable == true)
	//	{
	//		//pProp->crPosition.left = 0;
	//		//pProp->crPosition.right = 0;
	//		pProp->crPosition.right = (int)(cx * pProp->nXGrowthRatio + 
	//			(cx - _crDefWindowSize.Width()) * pProp->nXIndirectGrowthRatio);
	//	} else
	//	{
	//		pProp->crPosition.right = pProp->crDefPosition.Width();
	//	}
	//	//end alg v2.0 specific ----

	//}




	////
	////calculating Y
	////
	//n = _capChildrenPropertiesY.GetCount();
	//for(i=0; i<n; i++)
	//{
	//	pProp = _capChildrenPropertiesY[i];
	//	pProp->crPosition.top = 0;
	//	pProp->crPosition.bottom = 0;

	//	////calculating height
	//	//if (pProp->bYExpandable == true)
	//	//{
	//	//	pProp->crPosition.bottom = (int)(cy * pProp->nYGrowthRatio);
	//	//} else
	//	//{
	//	//	pProp->crPosition.bottom = pProp->crDefPosition.Height();
	//	//}

	//	////calculating position
	//	//space = _getDefMinSpaceY(pProp);
	//	//if (space < 0)
	//	//{
	//	//	pProp->crPosition.MoveToY(pProp->crDefPosition.top);
	//	//}
	//	//if (space >= 0)
	//	//{
	//	//	pCloseDep = _getClosestDependencyY(pProp);
	//	//	if (pCloseDep == NULL)
	//	//	{
	//	//		pProp->crPosition.MoveToY(pProp->crDefPosition.top);
	//	//	}
	//	//	if (pCloseDep != NULL)
	//	//	{
	//	//		pProp->crPosition.MoveToY(pCloseDep->crPosition.bottom + space);
	//	//	}
	//	//}

	//	//alg v2.0 specific --------
	//	if (pProp->bYExpandable == true)
	//	{
	//		//pProp->crPosition.top = 0;
	//		//pProp->crPosition.bottom = 0;
	//		pProp->crPosition.bottom = (int)(cy * pProp->nYGrowthRatio + 
	//			(cy - _crDefWindowSize.Height()) * pProp->nYIndirectGrowthRatio);
	//	} else
	//	{
	//		pProp->crPosition.bottom = pProp->crDefPosition.Height();
	//	}
	//	//end alg v2.0 specific ----
	//}


	n = _capChildrenPropertiesX.GetCount();
	for(i=0; i<n; i++)
	{
		pProp = _capChildrenPropertiesX[i];
		
		//pProp->crPosition.left = 0;
		//pProp->crPosition.right = 0;
		//pProp->crPosition.top = 0;
		//pProp->crPosition.bottom = 0;

		pWnd = GetDlgItem(pProp->wndID);
		if ((pWnd) || (pProp->hwndID))
		{
			if (pWnd)
			{
				::GetWindowRect(pWnd->GetSafeHwnd(), &pProp->crPosition);
				ScreenToClient(pProp->crPosition);
			} else
			{
				::GetWindowRect(pProp->hwndID, &pProp->crPosition);
				ScreenToClient(pProp->crPosition);
			}

			//X
			if (pProp->bXExpandable == true)
			{
				pProp->crPosition.right = pProp->crPosition.left + (int)(cx * pProp->nXGrowthRatio + 
					(cx - _crDefWindowSize.Width()) * pProp->nXIndirectGrowthRatio);
			}/* else
			{
				pProp->crPosition.right = pProp->crDefPosition.Width();
			}*/

			//Y
			if (pProp->bYExpandable == true)
			{
				pProp->crPosition.bottom = pProp->crPosition.top + (int)(cy * pProp->nYGrowthRatio + 
					(cy - _crDefWindowSize.Height()) * pProp->nYIndirectGrowthRatio);
			} /*else
			{
				pProp->crPosition.bottom = pProp->crDefPosition.Height();
			}*/
		}
	}
}


template <class BASECLASS>
void CResizeDlg<BASECLASS>::_onSize_alignRect(UINT nType, int cx, int cy)
{
	INT_PTR i, n;
	CWndProperties * pProp;
	CWndProperties * pMaster;
	int nMasterX;
	int nMasterY;
	CRect crMasterRect;
	CRect crMasterDefRect;

	n = _capChildrenPropertiesX.GetCount();
	for(i=0; i<n; i++)
	{
		pProp = _capChildrenPropertiesX[i];
		
		//
		//align on x
		//
		if ((pProp->wndMasterXID != 0) && (pProp->nXAxis != ALIGNMENT_AXIS_NO) && (pProp->nMasterXAxis != ALIGNMENT_AXIS_NO))
		{

			//main window is used
			if (pProp->wndMasterXID == ALIGNMENT_MasterID_DefWin)
			{
				//GetWindowRect( & crMasterRect);
				//crMasterRect.MoveToXY(0, 0);
				GetClientRect(crMasterRect);
				crMasterDefRect = _crDefWindowSize;
			} else
			{
				pMaster = getChildProperties(pProp->wndMasterXID);
				crMasterRect = pMaster->crPosition;
				crMasterDefRect = pMaster->crDefPosition;
			}
				
			//select master axis
			if (pProp->nMasterXAxis == ALIGNMENT_AXIS_1)
			{
				nMasterX = crMasterRect.left;
			}
			if (pProp->nMasterXAxis == ALIGNMENT_AXIS_2)
			{
				nMasterX = (crMasterRect.left + crMasterRect.right) / 2;
			}
			if (pProp->nMasterXAxis == ALIGNMENT_AXIS_3)
			{
				nMasterX = crMasterRect.right;
			}

			//alg v2.0 specific --------
			nMasterX += _offsetX(pProp, crMasterDefRect);
			//end alg v2.0 specific ----

			//select child window axis
			if (pProp->nXAxis == ALIGNMENT_AXIS_1)
			{
				pProp->crPosition.MoveToX(nMasterX);
			}
			if (pProp->nXAxis == ALIGNMENT_AXIS_2)
			{
				pProp->crPosition.MoveToX(nMasterX - pProp->crPosition.Width() / 2);
			}
			if (pProp->nXAxis == ALIGNMENT_AXIS_3)
			{
				pProp->crPosition.MoveToX(nMasterX - pProp->crPosition.Width());
			}
		}

	}
		

	n = _capChildrenPropertiesY.GetCount();
	for(i=0; i<n; i++)
	{
		pProp = _capChildrenPropertiesY[i];
		
		//
		//align on y
		//
		if ((pProp->wndMasterYID != 0) && (pProp->nYAxis != ALIGNMENT_AXIS_NO) && (pProp->nMasterYAxis != ALIGNMENT_AXIS_NO))
		{
			
			//main window is used
			if (pProp->wndMasterYID == ALIGNMENT_MasterID_DefWin)
			{
				//GetWindowRect( & crMasterRect);
				//crMasterRect.MoveToXY(0, 0);
				GetClientRect(crMasterRect);
				crMasterDefRect = _crDefWindowSize;
			} else
			{
				pMaster = getChildProperties(pProp->wndMasterYID);
				crMasterRect = pMaster->crPosition;
				crMasterDefRect = pMaster->crDefPosition;
			}

			//select master axis
			if (pProp->nMasterYAxis == ALIGNMENT_AXIS_4)
			{
				nMasterY = crMasterRect.top;
			}
			if (pProp->nMasterYAxis == ALIGNMENT_AXIS_5)
			{
				nMasterY = (crMasterRect.top + crMasterRect.bottom) / 2;
			}
			if (pProp->nMasterYAxis == ALIGNMENT_AXIS_6)
			{
				nMasterY = crMasterRect.bottom;
			}

			//alg v2.0 specific --------
			nMasterY += _offsetY(pProp, crMasterDefRect);
			//end alg v2.0 specific ----

			//select child window axis
			if (pProp->nYAxis == ALIGNMENT_AXIS_4)
			{
				pProp->crPosition.MoveToY(nMasterY);
			}
			if (pProp->nYAxis == ALIGNMENT_AXIS_5)
			{
				pProp->crPosition.MoveToY(nMasterY - pProp->crPosition.Height() / 2);
			}
			if (pProp->nYAxis == ALIGNMENT_AXIS_6)
			{
				pProp->crPosition.MoveToY(nMasterY - pProp->crPosition.Height());
			}

		}
	}
}


template <class BASECLASS>
int CResizeDlg<BASECLASS>::_offsetX(CWndProperties * pPropA, CRect & rcrMaster)
{
	int d = 0;

	if (pPropA->nXOffset == ALIGNMENT_AutoDetectOffset)
	{

		if (pPropA->nXAxis == ALIGNMENT_AXIS_VertLeft)
		{
			d = pPropA->crDefPosition.left;
		} else
		{
			if (pPropA->nXAxis == ALIGNMENT_AXIS_VertMid)
			{
				d = (pPropA->crDefPosition.left + pPropA->crDefPosition.right) / 2;
			} else
			{
				if (pPropA->nXAxis == ALIGNMENT_AXIS_VertRight)
				{
					d = pPropA->crDefPosition.right;
				} else
				{
					AfxMessageBox(_T("Invalid axis!"));
				}
			}
		}

		if (pPropA->nMasterXAxis == ALIGNMENT_AXIS_VertLeft)
		{
			d = d - rcrMaster.left;
		} else
		{
			if (pPropA->nMasterXAxis == ALIGNMENT_AXIS_VertMid)
			{
				d = d - (rcrMaster.left + rcrMaster.right) / 2;
			} else
			{
				if (pPropA->nMasterXAxis == ALIGNMENT_AXIS_VertRight)
				{
					d = d - rcrMaster.right;
				} else
				{
					AfxMessageBox(_T("Invalid axis!"));				
				}
			}
		}

		return d;
	}

	return pPropA->nXOffset;
}


template <class BASECLASS>
int CResizeDlg<BASECLASS>::_offsetY(CWndProperties * pPropA, CRect & rcrMaster)
{
	int d = 0;

	if (pPropA->nYOffset == ALIGNMENT_AutoDetectOffset)
	{

		if (pPropA->nYAxis == ALIGNMENT_AXIS_HorUp)
		{
			d = pPropA->crDefPosition.top;
		} else
		{
			if (pPropA->nYAxis == ALIGNMENT_AXIS_HorMid)
			{
				d = (pPropA->crDefPosition.top + pPropA->crDefPosition.bottom) / 2;
			} else
			{
				if (pPropA->nYAxis == ALIGNMENT_AXIS_HorDown)
				{
					d = pPropA->crDefPosition.bottom;
				} else
				{
					AfxMessageBox(_T("Invalid axis!"));
				}
			}
		}

		if (pPropA->nMasterYAxis == ALIGNMENT_AXIS_HorUp)
		{
			d = d - rcrMaster.top;
		} else
		{
			if (pPropA->nMasterYAxis == ALIGNMENT_AXIS_HorMid)
			{
				d = d - (rcrMaster.top + rcrMaster.bottom) / 2;
			} else
			{
				if (pPropA->nMasterYAxis == ALIGNMENT_AXIS_HorDown)
				{
					d = d - rcrMaster.bottom;
				} else
				{
					AfxMessageBox(_T("Invalid axis!"));
				}
			}
		}

		return d;
	}

	return pPropA->nYOffset;
}


template <class BASECLASS>
void CResizeDlg<BASECLASS>::_onSize_applayRect(UINT nType, int cx, int cy)
{
	INT_PTR i, n;
	CWndProperties * pProp;


//	if (sizeTotal.cx > rect.right - rect.left + 1 || sizeTotal.cy > rect.bottom - rect.top + 1)
	{
		n = _capChildrenProperties.GetCount();
		for(i=0; i<n; i++)
		{
			pProp = _capChildrenProperties[i];
			//automatic created windows
			if (pProp->hwndID == NULL)
			{
				//if (pProp->wndID == 1028)
				//{
				//	int a=0;
				//}
				::MoveWindow(
					GetDlgItem(pProp->wndID)->GetSafeHwnd(),
					pProp->crPosition.left + nXOffset,
					pProp->crPosition.top + nYOffset,
					pProp->crPosition.Width(),
					pProp->crPosition.Height(),
					TRUE);
			}
			//dinamic created windows at run-time
			if (pProp->hwndID != NULL)
			{
				::MoveWindow(
					pProp->hwndID,
					pProp->crPosition.left + nXOffset,
					pProp->crPosition.top + nYOffset,
					pProp->crPosition.Width(),
					pProp->crPosition.Height(),
					TRUE);
			}
		}
	}

	RedrawWindow(NULL, NULL, RDW_NOERASE);
}



template <class BASECLASS>
void CResizeDlg<BASECLASS>::_dbgShowAllDependencies()
{
	INT_PTR i, n;
	INT_PTR j, m;
	CWndProperties * pProp;
	CWndProperties * pPropIndirect;


	TRACE(_T("\r\n"));
	TRACE(_T("\r\n"));
	TRACE(_T("\r\nDirect and indirect dependents found-----------\r\n"));
	n = _capChildrenProperties.GetCount();
	for(i=0; i<n; i++)
	{
		pProp = _capChildrenProperties[i];
		TRACE(pProp->csText.GetBuffer());
		TRACE(_T(":\r\n"));

		m = pProp->capDirectXDependencies.GetCount();
		for(j=0; j<m; j++)
		{
			pPropIndirect = pProp->capDirectXDependencies[j];
			TRACE(_T("  x:"));
			TRACE(pPropIndirect->csText.GetBuffer());
			TRACE(_T("\r\n"));
		}

			m = pProp->capAllXDependencies.GetCount();
			for(j=0; j<m; j++)
			{
				pPropIndirect = pProp->capAllXDependencies[j];
				TRACE(_T("    x:"));
				TRACE(pPropIndirect->csText.GetBuffer());
				TRACE(_T("\r\n"));
			}

		m = pProp->capDirectYDependencies.GetCount();
		for(j=0; j<m; j++)
		{
			pPropIndirect = pProp->capDirectYDependencies[j];
			TRACE(_T("  y:"));
			TRACE(pPropIndirect->csText.GetBuffer());
			TRACE(_T("\r\n"));
		}

			m = pProp->capAllYDependencies.GetCount();
			for(j=0; j<m; j++)
			{
				pPropIndirect = pProp->capAllYDependencies[j];
				TRACE(_T("    y:"));
				TRACE(pPropIndirect->csText.GetBuffer());
				TRACE(_T("\r\n"));
			}
	}

	TRACE(_T("\r\nCalculate order by x---------------------------\r\n"));
	n = _capChildrenPropertiesX.GetCount();
	for(i=0; i<n; i++)
	{
		pProp = _capChildrenPropertiesX[i];
		TRACE(pProp->csText.GetBuffer());
		TRACE(_T("\r\n"));
	}

	TRACE(_T("\r\nCalculate order by y---------------------------\r\n"));
	n = _capChildrenPropertiesY.GetCount();
	for(i=0; i<n; i++)
	{
		pProp = _capChildrenPropertiesY[i];
		TRACE(pProp->csText.GetBuffer());
		TRACE(_T("\r\n"));
	}


	TRACE(_T("\r\n"));
}



typedef CResizeDlg<CDialogEx> CResizeDlgCtrl;
typedef CResizeDlg<CFormView> CResizeFormView;